package com.seanliao.nav.common.exception;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.StrUtil;
import com.seanliao.nav.common.enums.ResultCodeEnum;
import com.seanliao.nav.common.response.Result;
import com.seanliao.nav.common.response.ResultBuilder;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 *
 * @author Sean_Liao
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 事务异常
     */
    @ExceptionHandler(BusinessException.class)
    public Result<?> businessException(BusinessException ex) {
        return ResultBuilder.fail(ex.getCode(), ex.getMessage());
    }

    /**
     * 请求参数异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<?> methodArgumentNotValidException(MethodArgumentNotValidException ex) {
        log.error("参数异常:", ex);
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        String message = allErrors.stream().map(objectError->{
            if (objectError instanceof FieldError fieldError){
                return  fieldError.getField() + fieldError.getDefaultMessage();
            }else{
                return objectError.getDefaultMessage();
            }
        }).collect(Collectors.joining(";"));
        return ResultBuilder.fail(message);
    }

    /**
     * 令牌验证异常
     */
    @ExceptionHandler(ValidateException.class)
    public Result<?> validateException(ValidateException ex) {
        log.error("token验证异常......", ex);
        return ResultBuilder.fail(ResultCodeEnum.TOKEN_ERR.getCode(), "登录状态异常，请重新登录");
    }


    /**
     * 权限异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public Result<?> accessDeniedException(AccessDeniedException ex) {
        return ResultBuilder.fail("无此权限");
    }

    /**
     * 一般异常
     */
    @ExceptionHandler(Exception.class)
    public Result<?> exception(HttpServletRequest request, Exception ex) {
        log.error(StrUtil.format("request URI:{}", request.getRequestURI()), ex);
        return ResultBuilder.fail("服务器异常");
    }
}
